#include "exec.h"
using namespace std;

void doMain();    //主要流程
void doAct();     //操作选择
bool addMsg();    //添加信息
bool delMsg();    //删除信息
bool searchMsg(); //查找信息
bool writeMsg();  //修改信息
/*
 *主要流程模块 
 *功能：调用各个函数模块，控制流程
 */
void doMain()
{
    printf("loading database...\n");
    loadDB();
    printf("finished\n");
    system("CLS");
    doAct(); //进入操作选择
}

/*
 *操作选择模块 
 *功能：调用增删查改操作
 */
void doAct()
{
    while (1)
    {
        printf("===============================================================================\n");
        printf("=============               Here is your databases                 ============\n");
        showDatabase(dbPointer);
        printf("\n==============================================================================\n");
        printf("===========                   1->add                             =============\n");
        printf("===========                   2->delete                          =============\n");
        printf("===========                   3->write                           =============\n");
        printf("===========                   4->search                          =============\n");
        printf("===========                   else->exit                         =============\n");
        printf("==============================================================================\n");
        printf("Please enter your operator number: \n");
        int handle;
        scanf("%d", &handle);
        switch (handle)
        {
        case 1:
            addMsg();
            break;
        case 2:
            delMsg();
            break;
        case 3:
            writeMsg();
            break;
        case 4:
            searchMsg();
            break;
        default:
            printf("error input!\n");
            break;
        }
        
        if (handle != 1 && handle != 2 && handle != 3 && handle != 4)
            break;
    }
}

/*
 *增加模块 
 *功能：增加数据
 */
bool addMsg()
{
    printf("\n================================================================================\n");
    printf("===========                   1->add database                      =============\n");
    printf("===========                   2->add table                         =============\n");
    printf("===========                   3->add data                          =============\n");
    printf("===========                   else->exit                           =============\n");
    printf("================================================================================\n");
    printf("Please make your choice:\n");
    int num;
    scanf("%d",&num);
    switch (num)
    {
        //添加数据库
        case 1:{
            printf("Enter the name of the DATABASENAME to be added: \n");
            //数据库名
            string databaseName;
            cin >> databaseName;
            
            string dbName;
            string prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
            //数据库不存在则创建数据库
            if(_access(dbName.c_str(),0) == -1){
                _mkdir(dbName.c_str());
                //更新结构体的值
                dbBlock* db = new dbBlock();
                db->n = 0;
                db->name = (char*)databaseName.c_str();
                dbBlock *p = dbPointer;
                while(p->next != NULL){
                    p = p->next;
                }
                p->next = db;
                db->next = NULL;
                //数据块个数加1
                countDB++;
            }
            printf("add success\n");
            break;
        }

        //添加数据表
        case 2:{
            printf("Enter the DATABASENAME of the dataTable to be added: \n");
            //数据库名
            string databaseName;
            cin >> databaseName;
            string dbName;
            string prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
            while(_access(dbName.c_str(),0) == -1){
                printf("The DATABASENAME you entered does not exist. Please re-enter: \n");
                cin >> databaseName;
                prefix = "./dbFile/";
                dbName = prefix.append(databaseName);
            }
            
            //找到当前数据库的指针
            dbBlock* p = dbPointer;
            while(strcmp(p->name,databaseName.c_str()) != 0){
                p = p->next;
            }
            
            printf("Enter the name of the data table to be added: \n");
            string dataTableName;
            cin >> dataTableName;

            string tName;
            tName = dbName.append("/").append(dataTableName);

            //文件指针
            FILE *fileP;
            fileP = fopen(tName.c_str(),"r");
            while(fileP != NULL){
                printf("Datatable already exists, please re-enter: \n");
                cin >> dataTableName;
                tName = dbName.append("/").append(dataTableName);
                fileP = fopen(tName.c_str(),"r");
            }
            //使用写入方式创建文件
            fileP = fopen(tName.c_str(), "w");
            if(p->n == 0){
                p->n = 1;
                tbBlock *tb = new tbBlock();
                tb->name = (char*)dataTableName.c_str();
                tb->next = NULL;
                tb->abbr = NULL;
                tb->dataPointer = NULL;
                tb->abbr_n = 0;
                p->tbPointer = tb;
            }
            fclose(fileP);
            printf("add success\n");
            break;
        }

        //添加数据
        case 3:{
            printf("Enter the DATABASENAME of the data to be added: \n");
            //数据库名
            string databaseName;
            cin >> databaseName;
            string dbName;
            string prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
            
            while(_access(dbName.c_str(),0) == -1){
                printf("The database name you entered does not exist. Please re-enter: \n");
                cin >> databaseName;
                prefix = "./dbFile/";
                dbName = prefix.append(databaseName);
                cout << "db=" << dbName << endl;
            }
            
            //找到当前数据库的指针
            dbBlock* p = dbPointer;
            while(strcmp(p->name,databaseName.c_str()) != 0){
                p = p->next;
            }

            printf("Enter the DATATABLE of the data to be added: \n");
            //数据表名
            string dataTableName;
            cin >> dataTableName;

            string tName;
            tName = dbName+"/"+dataTableName;
            //文件指针
            FILE *fileP;
            fileP = fopen(tName.c_str(),"r");
            while(fileP == NULL){
                printf("Datatable not  exists, please re-enter: \n");
                cin >> dataTableName;
                tName = dbName+"/"+dataTableName;
                fileP = fopen(tName.c_str(),"r");
                // cout << "tNAMe=" << tName << endl;
            }
            
            //找到当前表指针
            tbBlock* t = p->tbPointer;
            while(strcmp(t->name,dataTableName.c_str()) != 0){
                t = t->next;
            }
            fclose(fileP);
            fileP = fopen((tName).c_str(),"a+");
            cout << "fileName = " << tName << endl;
            //区分添加数据属性和数据内容
            int tmp;
            printf("Enter the number of operands you want to perform: \n");
            printf("Enter your choice: 1->add attribute  2->add data \n");
            scanf("%d",&tmp);

            if(tmp == 1){
                printf("Enter the number of attributes you want to add: \n");
                int numAttr;
                scanf("%d",&numAttr);

                printf("Enter the value of attributes you want to add: \n");
                for(int i = 0; i < numAttr; i++){
                    string name;
                    cin >> name;
                    fprintf(fileP,name.c_str());
                    fprintf(fileP," ");
                }
                fprintf(fileP,"\n");
                printf("add success\n");
            }
            else if(tmp == 2){
                printf("Enter the DATA to be added: \n");
                dbBlock* db = dbPointer;
                tbBlock* tb = NULL;
                dataBlock* dataB = NULL;
                Abbr* attr = NULL;
                int num = 0;

                while(db != NULL && strcmp(db->name,databaseName.c_str()) != 0){
                    db = db->next;
                }
                if(db != NULL){
                    tb = db->tbPointer;
                    while(tb != NULL && strcmp(tb->name,dataTableName.c_str()) != 0){
                        tb = tb->next;
                    }
                    if(tb != NULL){
                        attr = tb->abbr;
                        while(attr != NULL){
                            printf("%s  ",attr->name);
                            attr = attr->next;
                            num++;
                        }
                        printf("\n");
                        //输入数据个数
                        dataB = tb->dataPointer;
                        while(dataB != NULL){
                            dataB = dataB->next;
                        }
                        dataB = new dataBlock();
                        // dataB->n = num;
                        dataB->value = new int[num];
                        int i = 0;
                        for(i = 0; i < num; i++){
                            scanf("%d",&dataB->value[i]);
                            fprintf(fileP,"%d",dataB->value[i]);
                            fprintf(fileP,"    ");
                        }
                        fprintf(fileP,"\n");
                        dataB->next = NULL;
                        printf("add success\n");
                    }
                }
            }
            fclose(fileP);
            loadDB();
            break;
        }
        default:
            printf("exiting...\n");
            break;
    }
    loadDB();
    system("pause");
}

/*
 *删除模块 
 *功能：删除数据
 */
bool delMsg()
{
    printf("\n================================================================================\n");
    printf("===========                   1->delete database                   =============\n");
    printf("===========                   2->delete table                      =============\n");
    printf("===========                   3->delete data                       =============\n");
    printf("===========                   else->exit                           =============\n");
    printf("================================================================================\n");
    printf("Please make your choice:\n");
    int num;
    scanf("%d",&num);
    switch (num)
    {
        //删除数据库
        case 1:{
            printf("Enter the name of the DATABASENAME to be deleted\n");
            //数据库名
            string databaseName;
            cin >> databaseName;
            
            string dbName;
            string prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
            //数据库存在则删除数据库
            if(_access(dbName.c_str(),0) != -1){
                // cout << "///" << endl;
                rmdir(dbName.c_str());
                printf("delete success!\n");
            }
            else{
                printf("the database not exists!\n");
            }
            break;
        }

        //添加数据表
        case 2:{
            printf("Enter the DATABASENAME of the dataTable to be deleted: \n");
            //数据库名
            string databaseName;
            cin >> databaseName;
            string dbName;
            string prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
            while(_access(dbName.c_str(),0) == -1){
                printf("The DATABASENAME you entered does not exist. Please re-enter: \n");
                cin >> databaseName;
                prefix = "./dbFile/";
                dbName = prefix.append(databaseName);
            }
            
            printf("Enter the name of the data table to be deleted: \n");
            string dataTableName;
            cin >> dataTableName;

            string tName;
            tName = dbName.append("/").append(dataTableName);

            //文件指针
            FILE *fileP;
            fileP = fopen(tName.c_str(),"r");
            while(fileP == NULL){
                printf("Datatable not exists, please re-enter: \n");
                cin >> dataTableName;
                tName = dbName.append("/").append(dataTableName);
                fileP = fopen(tName.c_str(),"r");
            } 
            fclose(fileP);
            //删除文件
           if(unlink(tName.c_str()) == -1){
               cout << "Could not delete " << tName << endl;
           }
           else{
               cout << "Has deleted " << tName << endl;
           }
           
            break;
        }

        //删除数据
        case 3:{
            printf("Enter the DATABASENAME of the data to be deleted: \n");
            //数据库名
            string databaseName;
            cin >> databaseName;
            string dbName;
            string prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
            while(_access(dbName.c_str(),0) == -1){
                printf("The database name you entered does not exist. Please re-enter: \n");
                cin >> databaseName;
                prefix = "./dbFile/";
                dbName = prefix.append(databaseName);
            }
            
            printf("Enter the DATATABLE of the data to be deleted: \n");
            //数据表名
            string dataTableName;
            cin >> dataTableName;
            string tmpPath = dbName;
            string tName;
            tName = dbName.append("/").append(dataTableName);
            tmpPath = tmpPath.append("/tmp").append(dataTableName);
            //文件指针
            FILE *fileP,*fileP_out;
            fileP = fopen(tName.c_str(),"r");
            while(fileP == NULL){
                printf("DataTable not exists, please re-enter: \n");
                cin >> dataTableName;
                tName = dbName.append("/").append(dataTableName);
                fileP = fopen(tName.c_str(),"r");
                // if(dataTableName == "-1"){
                //     goto end;
                // }
            }

            fileP_out = fopen(tmpPath.c_str(),"w"); 
            printf("Enter the primary key of DATA to be deleted: \n");
            //主码
            int primaryKey;
            scanf("%d",&primaryKey);
            char line[1024];
            string data;
            int t = 0;
            while (fgets(line,1024,fileP) != NULL)
            {
                data = line;
                char* token = strtok(line," ");
                if(primaryKey != atoi(token)){
                    fprintf(fileP_out,data.c_str());
                }
            }
            fclose(fileP);
            fclose(fileP_out);
            remove(tName.c_str());
            rename(tmpPath.c_str(),tName.c_str());
            printf("delete success!\n");
            break;
        }
        default:
            printf("exiting...\n");
            break;
    }

    loadDB();
    system("pause");
}


/*
 *修改模块 
 *功能：修改数据
 */
bool writeMsg()
{
    printf("\n================================================================================\n");
    printf("===========                   1->moidfy database                   =============\n");
    printf("===========                   2->moidfy table                      =============\n");
    printf("===========                   3->modify data                       =============\n");
    printf("===========                   else->exit                           =============\n");
    printf("================================================================================\n");
    printf("Please make your choice:\n");
    int handle;
    cin >> handle;

    switch (handle)
    {
    case 1:{
        /* code */
        
        cout << "Enter the name of the database to be modified: " << endl;
        string oldDbName,newDbName;
        cin >> oldDbName;
        string oldName,newName;
        string prefix = "./dbFile/";
        oldName = prefix + oldDbName;
        while(_access(oldName.c_str(),0) == -1){
                printf("The database name you entered does not exist. Please re-enter: \n");
                cin >> oldDbName;
                prefix = "./dbFile/";
                oldName = prefix + oldName;
        }
        printf("Enter a new database name: ");
        cin >> newDbName;
        newName = prefix + newDbName;
        if(rename(oldName.c_str(),newName.c_str()) == 0){
            printf("modify success!\n");
        }
        else{
            printf("modify fail!\n");
        }
        break;
    }
        

    case 2:{
        /* code */
        cout << "Enter the name of database you choose: " << endl;
        //数据库名
        string databaseName;
        cin >> databaseName;
        string dbName;
        string prefix = "./dbFile/";
        dbName = prefix.append(databaseName);
        while(_access(dbName.c_str(),0) == -1){
            printf("The database name you entered does not exist. Please re-enter: \n");
            cin >> databaseName;
            prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
        }

        printf("Enter the name of the dataTable to be changed: \n");
        string dataTableName;
        cin >> dataTableName;

        string oldTableName;
        oldTableName = dbName + "/" + dataTableName;
        //文件指针
        FILE *fileP;
        fileP = fopen(oldTableName.c_str(),"r");
        while(fileP == NULL){
            printf("DataTable not exists, please re-enter: \n");
            cin >> dataTableName;
            oldTableName = dbName + "/" + dataTableName;
            fileP = fopen(oldTableName.c_str(),"r");
        } 
        fclose(fileP);

        printf("Enter the new name of the dataTbale to be changed: \n");
        string newTableName;
        cin >> newTableName;
        newTableName = dbName + "/" + newTableName;

        if(rename(oldTableName.c_str(),newTableName.c_str()) == 0){
            printf("modify success!\n");
        }
        else{
            printf("modify fail!\n");
        }
        break;
    }
        

    case 3:{
        /* code */
        cout << "Enter the name of database you choose: " << endl;

        //数据库名
        string databaseName;
        cin >> databaseName;
        string dbName;
        string prefix = "./dbFile/";
        dbName = prefix.append(databaseName);
        while(_access(dbName.c_str(),0) == -1){
            printf("The database name you entered does not exist. Please re-enter: \n");
            cin >> databaseName;
            prefix = "./dbFile/";
            dbName = prefix.append(databaseName);
        }

        printf("Enter the DATATABLE of the data to be changed: \n");
        //数据表名
        string dataTableName;
        cin >> dataTableName;
        string tmpPath = dbName;
        string tName;
        tName = dbName.append("/").append(dataTableName);
        tmpPath = tmpPath.append("/tmp").append(dataTableName);
        //文件指针
        FILE *fileP,*fileP_out;
        fileP = fopen(tName.c_str(),"r");
        while(fileP == NULL){
            printf("DataTable not exists, please re-enter: \n");
            cin >> dataTableName;
            tName = dbName.append("/").append(dataTableName);
            fileP = fopen(tName.c_str(),"r");
        }

        fileP_out = fopen(tmpPath.c_str(),"w"); 


        //读取数据表属性信息：
        dbBlock* db = dbPointer;
        tbBlock* tb = NULL;
        dataBlock* dataB = NULL;
        Abbr* attr = NULL;
        int num = 0;

        printf("There are datatable's attribtions: \n");
        while(db != NULL && strcmp(db->name,databaseName.c_str()) != 0){
            db = db->next;
        }
        if(db != NULL){
            tb = db->tbPointer;
            
            while(tb != NULL && strcmp(tb->name,dataTableName.c_str()) != 0){
                tb = tb->next;
            }
            if(tb != NULL){
                attr = tb->abbr;
                
                while(attr != NULL){
                    num += 1;
                    printf("%s\t",attr->name);
                    attr = attr->next;
                }
                printf("\n");
            }
        }
        printf("Enter the primary key of DATA to be changed: \n");
        //主码
        int primaryKey;
        scanf("%d",&primaryKey);
        printf("Enter the new value of the line attribute: \n");
        int *value = new int[num];
        string newValue = "";
        char str[20];
        for(int i = 0; i < num; i++){
            scanf("%d",&value[i]);
             newValue = newValue + itoa(value[i],str,10) + " ";
        }
        
        newValue += "\n";
        // cout << newValue << endl;
        //读取文件修改数据
        char line[1024];
        string data;
        int t = 0;
        while(fgets(line,1024,fileP) != NULL){
            data = line;
            t = 0;
            char* token = strtok(line," ");
            if(primaryKey != atoi(token)){
                fprintf(fileP_out,data.c_str());
                
            }
            else{
                fprintf(fileP_out,newValue.c_str());
            }
        }
        fclose(fileP);
        fclose(fileP_out);
        remove(tName.c_str());
        rename(tmpPath.c_str(),tName.c_str());
        printf("modify success!\n");
        break;
    }
        
    default:
        printf("exit...\n");
        break;
    }
    loadDB();
    system("pause");
}

/*
 *查询模块 
 *功能：增加数据
 */
bool searchMsg()
{
    printf("\n================================================================================\n");
    printf("===========                   1->search database                   =============\n");
    printf("===========                   2->search table                      =============\n");
    printf("===========                   3->search data                       =============\n");
    printf("===========                   else->exit                           =============\n");
    printf("================================================================================\n");
    printf("Please make your choice:\n");
    int handle;
    cin >> handle;

    dbBlock *db_t;
    tbBlock *tb_t;
    dataBlock *data_t;
    char dbName[1024];

    switch (handle)
    {
    case 1:
        /* code */
        cout << "Enter database name: " << endl;
        cin >> dbName;
        db_t = dbPointer;

        while (db_t != NULL)
        {
            if (strcmp(db_t->name, dbName) == 0)
            {
                showTable(db_t->tbPointer);
                break;
            }
            
                db_t = db_t->next;
        }
        break;

    case 2:
        /* code */
        cout << "Enter the name of database you choose: "  << endl;
        cin >> dbName;
        db_t = dbPointer;
        while (db_t != NULL)
        {
            if (strcmp(db_t->name, dbName) == 0)
                break;
            db_t = db_t->next;
        }
        if (db_t != NULL)
        {
            cout << "Enter table name: "  << endl;
            char tbName[1024];
            cin >> tbName;

            tb_t = db_t->tbPointer;
            while (tb_t != NULL)
            {
                if (strcmp(tb_t->name, tbName) == 0)
                {
                    //输出标签
                    Abbr *abbr_t = tb_t->abbr;
                    while (abbr_t != NULL)
                    {
                        cout << abbr_t->name << " ";
                        abbr_t = abbr_t->next;
                    }
                    cout << endl;

                    //输出数据
                    data_t = tb_t->dataPointer;
                    while (data_t != NULL)
                    {
                        for (int i = 0; i < data_t->n; i++)
                        {
                            cout << data_t->value[i] << "   ";
                        }
                        cout << endl;
                        data_t = data_t->next;
                    }
                    break;
                }
                tb_t = tb_t->next;
            }
        }
        break;

    case 3:
        /* code */
        cout << "Enter the name of database you choose: "  << endl;
        char dbName[1024];
        cin >> dbName;

        db_t = dbPointer;
        while (db_t != NULL)
        {
            if (strcmp(db_t->name, dbName) == 0)
                break;
            db_t = db_t->next;
        }

        if (db_t != NULL)
        {
            cout << "Enter table name you choose: "  << endl;
            char tbName[1024];
            cin >> tbName;

            tb_t = db_t->tbPointer;
            while (tb_t != NULL)
            {
                if (strcmp(tb_t->name, tbName) == 0)
                {
                    break;
                }
                tb_t = tb_t->next;
            }

            if (tb_t != NULL)
            {
                cout << "Enter the primary key: "  << endl;
                int pK;
                cin >> pK;

                //输出标签
                Abbr *abbr_t = tb_t->abbr;
                while (abbr_t != NULL)
                {
                    cout << abbr_t->name << " ";
                    abbr_t = abbr_t->next;
                }
                cout << endl;

                //输出数据
                data_t = tb_t->dataPointer;
                while (data_t != NULL)
                {
                    if (data_t->value[0] == pK)
                    {
                        for (int i = 0; i < data_t->n; i++)
                        {
                            cout << data_t->value[i] << "   ";
                        }
                        cout << endl;
                        break;
                    }
                    data_t = data_t->next;
                }
            }
        }
        break;

    default:
        printf("exit...\n");
        break;
    }
    loadDB();
    system("pause");
}